/*
 * Created on Oct 22, 2004
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.hermeneute.fsa;

import java.util.Collections;
import java.util.Iterator;
import java.util.Vector;

/**
 * @author mauceri
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

class TransCell {
	int idx;
	FSTCompiledTransition tr;
	TransCell(int i,FSTCompiledTransition t){
		idx = i;
		tr = t;
	}
}

public class FSTSequentialMediumCompiledState implements FSTSequentialCompiledState {

	/* (non-Javadoc)
	 * @see com.hermeneute.fst.FSTSequentialCompiledState#nextState(char)
	 */
	public FSTCompiledTransition epsilonNext = null;
	public FSTCompiledTransition anyNext = null;
	
	TransCell table[];
	
	public FSTSequentialMediumCompiledState(FSTTransitionIterator it, int idx[]){
		Vector tmp = new Vector();
		int i;
		
		while(it.hasNext()){
			it.next();
			
			if ((int)it.getEvent().getIn() == FSTEvent.Epsilon) {
				//System.out.println("Epsilon trans");
				epsilonNext = new FSTCompiledTransition(it.getState(),it.getEvent().getOut());
				tmp.add(it.getTransition());
			} else if ((int)it.getEvent().getIn() == FSTEvent.Any) {
				//System.out.println("Any trans");
				anyNext = new FSTCompiledTransition(it.getState(),it.getEvent().getOut());
				tmp.add(it.getTransition());
			}else {
				tmp.add(it.getTransition());
			}
		}
		Collections.sort(tmp,new FSTInputTransitionComparator(idx));
		table = new TransCell[tmp.size()];
		i = 0;
		for (Iterator lit = tmp.iterator();lit.hasNext();i++){
			FSTTransition t = (FSTTransition)lit.next();
			FSTCompiledTransition ct = new FSTCompiledTransition(
					t.getState(),
					t.getEvent().getOut());
			table[i] = new TransCell(idx[(int)t.getEvent().getIn()],ct);
			//System.out.println(idx[(int)t.getEvent().getIn()]+" = "+t.getEvent().getIn());
		}
	}

	public FSTCompiledTransition nextState(int input) {
		//System.out.println("Looking for : "+input);
		/*if (input == FSTEvent.Epsilon) {
			//System.out.println("Ein epsilon");
			return epsilonNext;
		}
		if (input == FSTEvent.Any) {
			//System.out.println("Ein Any");
			return anyNext;
		}*/
		int max = table.length;
		int min = 0;
		int pos = max/2;
		int delta = 0;
		boolean found = false;
		boolean carryon = true;
		/*for (int i = 0; i< table.length;i++){
			System.out.println(i+" "+table[i].idx+" "+table[i].tr.output);
		}*/
		while (!found && carryon){
			//System.out.println(input+" min = "+min+" max = "+max+" pos = "+pos);
			if (table[pos].idx == input) {
				//System.out.println(input+" found");
				found = true;
			}else if (table[pos].idx < input){
				if (pos == min || pos == max) carryon = false;
				min = pos;
				delta = (max-min)/2;
				pos = min+delta;
			}else {
				if (pos == min || pos == max) carryon = false;
				max = pos;
				delta = (max-min)/2;
				pos = min+delta;
			}
		}
		
		if (found){
			//System.out.println(input+" found");
			return table[pos].tr;
		}else if (pos+1 == table.length-1 && table[pos+1].idx == input) {
			return table[pos+1].tr;
		}else {
			return null;
		}			
	}

	/* (non-Javadoc)
	 * @see com.hermeneute.fst.FSTSequentialCompiledState#getType()
	 */
	public int getType() {
		// TODO Auto-generated method stub
		return FSTSequentialCompiledState.MEDIUM_STATE;
	}

}
